home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-04-05 | 57.3 KB | 2,111 lines |
- (Message mh:7)
- Resent: Mon, 25 Mar 91 10:19:03 PST
- Resent: qq11@uxb.liv.ac.uk (Alan Thew)
- Resent: Mon, 18 Mar 91 12:22:10 PST
- Resent: jcohn@nsf.gov (Johnathan Charles Cohn)
- Resent: rjg@sq.com (Bob Gibson)
- Resent: dak@sq.com (David Keldson)
- Resent: sow@cad.luth.se (Sven-Ove Westberg)
- Resent: cenkl@linus.mitre.org (Mike Cenkl)
- Resent: david@scocan.sco.com (David J Fiander)
- Return-Path: jamesp@metolius.WR
- To: luj@ecn.purdue.edu (Jun Lu), jkm@ctt.bellcore.COM (James Mcglashan),
- jmvogtle@gamera.cns.syr.edu (John M Vogtle),
- cks@hawkwind.utcs.toronto.edu (Chris Siebenmann),
- ccw@deakin.OZ.AU (Craig Warren), rr@mips.COM (Robert "Bob" Rodriguez),
- munck@Stars.Reston.Unisys.COM (Bob Munck)
- Cc: jamesp@metolius.WR.TEK.COM (James Perkins)
- Subject: Vmail - version 10/87DAS - part 2/3
- Reply-To: jamesp@metolius.WR.TEK.COM (James T. Perkins)
- Reply-To: traveller-request@metolius.WR.TEK.COM (TML Administrator)
- X-Mailer: Rand MH 6.6 - Vmail 10/87DAS - Vmailtool V1.14 91/02/27
- Date: Mon, 11 Mar 91 11:43:48 PST
- From: James T Perkins <jamesp@metolius.WR>
- --------
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: call.c init.c main.c move.c vmail.1
- # Wrapped by jamesp@metolius on Mon Mar 11 11:20:04 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f call.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"call.c\"
- else
- echo shar: Extracting \"call.c\" \(10995 characters\)
- sed "s/^X//" >call.c <<'END_OF_call.c'
- X#ifndef lint
- Xstatic char *RCS_call_c = "$Id: call.c,v 1.5 90/09/19 13:53:33 rogers Exp $";
- X#endif
- X
- X/* --------------------
- X vmail -- call.c
- X
- X Routines that call MH equivalents, editor, shell.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X#include <signal.h>
- X
- X#define WARNING "Warning -- mail headers may be out of date"
- X
- Xunion wait status;
- X
- X/* --------------------
- X Fork a call to `comp'.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xcomp()
- X{
- X char *tmp, *argv[20], str[LEN], s1[LEN], *next_token();
- X int i;
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X *s1 = '\0';
- X if(comp_args) {
- X (void)sprintf(str, "(give options to) comp ");
- X get_string(str, s1);
- X }
- X clear();
- X addstatus("composing mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X argv[0] = COMP;
- X for(i=1, tmp=s1 ; *tmp != '\0' ; i++) {
- X argv[i] = tmp;
- X tmp = next_token(tmp);
- X }
- X argv[i] = 0;
- X no_control();
- X execvp(COMP, argv);
- X (void)printf("Warning: can't execute %s\n", COMP);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X addstatus(WARNING, true); /* vmail's data structures not updated */
- X}
- X
- X
- X/* --------------------
- X Fork a call to `forw'.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xforw()
- X{
- X char *tmp, *argv[20], str[LEN], s1[LEN], s2[10], *next_token();
- X int i;
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X (void)sprintf(s2, "%d", curmail->number);
- X *s1 = '\0';
- X if(forw_args) {
- X (void)sprintf(str, "(give options to) forw +%s %s ", curflr->name, s2);
- X get_string(str, s1);
- X }
- X clear();
- X addstatus("forwarding mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X (void)sprintf(str, "+%s", curflr->name);
- X argv[0] = FORW; argv[1] = str; argv[2] = s2;
- X for(i=3, tmp=s1 ; *tmp != '\0' ; i++) {
- X argv[i] = tmp;
- X tmp = next_token(tmp);
- X }
- X argv[i] = 0;
- X no_control();
- X execvp(FORW, argv);
- X (void)printf("Warning: can't execute %s\n", FORW);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X addstatus(WARNING, true); /* vmail's data structures not updated */
- X}
- X
- X
- X/* --------------------
- X Fork a call to `repl'.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xrepl()
- X{
- X char *tmp, *argv[20], str[LEN], s1[LEN], s2[10], *next_token();
- X int i;
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X (void)sprintf(s2, "%d", curmail->number);
- X *s1 = '\0';
- X if(repl_args) {
- X (void)sprintf(str, "(give options to) repl +%s %s ", curflr->name, s2);
- X get_string(str, s1);
- X }
- X clear();
- X addstatus("answering mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X (void)sprintf(str, "+%s", curflr->name);
- X argv[0] = REPL; argv[1] = str; argv[2] = s2;
- X for(i=3, tmp=s1 ; *tmp != '\0' ; i++) {
- X argv[i] = tmp;
- X tmp = next_token(tmp);
- X }
- X argv[i] = 0;
- X no_control();
- X execvp(REPL, argv);
- X (void)printf("Warning: can't execute %s\n", REPL);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X addstatus(WARNING, true); /* vmail's data structures not updated */
- X}
- X
- X
- X/* --------------------
- X Fork a call to editor.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xedit()
- X{
- X char str[LEN];
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X clear();
- X mvaddstr(TITLE, 0, "editing mail ...");
- X move(STATUS, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X no_control();
- X (void)sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
- X execlp(editor, editor, str, 0);
- X (void)printf("Warning: can't execute %s\n", editor);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X addstatus(WARNING, true); /* vmail's data structures not updated */
- X}
- X
- X
- X/* --------------------
- X Fork a call to shell.
- X Terminal type must be reset before call.
- X
- X This should perhaps be modified so that only a single command can be
- X issued, as in vi ... but this was simpler to do.
- X-------------------- */
- Xvoid
- Xcall_shell()
- X{
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X clear();
- X mvaddstr(TITLE, 0, "calling shell ...");
- X move(STATUS, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X no_control();
- X fix_mh();
- X execlp(shell, shell, "-i", 0);
- X (void)printf("Warning: can't execute %s\n", shell);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X}
- X
- X
- X/* --------------------
- X Pipe current mail item into given command.
- X-------------------- */
- Xvoid
- Xdo_pipe()
- X{
- X char str[LEN], s1[LEN];
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X *s1 = '\0';
- X (void)sprintf(str, "(give command to) show +%s %d | ", curflr->name,
- X curmail->number);
- X get_string(str, s1);
- X clear();
- X addstatus("piping mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X (void)sprintf(str, "%s %s/%s/%d | %s", CAT, mail_dir, curflr->name,
- X curmail->number, s1);
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X no_control();
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)system(str); /* exec needs full path of command => use system */
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X}
- X
- X/* --------------------
- X Fork a call to `burst'.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xburst_item()
- X{
- X char *tmp, *argv[20], str[LEN], s1[LEN], s2[10], *next_token();
- X int i;
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X (void)sprintf(s2, "%d", curmail->number);
- X *s1 = '\0';
- X if(burst_args) {
- X (void)sprintf(str, "(give options to) burst +%s %s ", curflr->name, s2);
- X get_string(str, s1);
- X }
- X clear();
- X addstatus("bursting mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X (void)sprintf(str, "+%s", curflr->name);
- X argv[0] = BURST; argv[1] = str; argv[2] = s2;
- X for(i=3, tmp=s1 ; *tmp != '\0' ; i++) {
- X argv[i] = tmp;
- X tmp = next_token(tmp);
- X }
- X argv[i] = 0;
- X no_control();
- X execvp(BURST, argv);
- X (void)printf("Warning: can't execute %s\n", BURST);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X clear();
- X move(STATUS, 0);
- X refresh_folder();
- X}
- X
- X/* --------------------
- X Fork a call to `dist'.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xdist_item()
- X{
- X char *tmp, *argv[20], str[LEN], s1[LEN], s2[10], *next_token();
- X int i;
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X (void)sprintf(s2, "%d", curmail->number);
- X *s1 = '\0';
- X if(dist_args) {
- X (void)sprintf(str, "(give options to) dist +%s %s ", curflr->name, s2);
- X get_string(str, s1);
- X }
- X clear();
- X addstatus("disting mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X (void)sprintf(str, "+%s", curflr->name);
- X argv[0] = DIST; argv[1] = str; argv[2] = s2;
- X for(i=3, tmp=s1 ; *tmp != '\0' ; i++) {
- X argv[i] = tmp;
- X tmp = next_token(tmp);
- X }
- X argv[i] = 0;
- X no_control();
- X execvp(DIST, argv);
- X (void)printf("Warning: can't execute %s\n", DIST);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X display_page();
- X addstatus(WARNING, true); /* vmail's data structures not updated */
- X}
- X
- X/* --------------------
- X Fork a call to `sortm'.
- X Terminal type must be reset before call.
- X-------------------- */
- Xvoid
- Xsort_folder()
- X{
- X char *tmp, *argv[20], str[LEN], s1[LEN], *next_token();
- X int i;
- X sig_type (*oldint)(), (*oldquit)(), (*signal())();
- X
- X *s1 = '\0';
- X if(sort_args) {
- X (void)sprintf(str, "(give options to) sortm +%s ", curflr->name);
- X get_string(str, s1);
- X }
- X clear();
- X addstatus("sorting mail ...", false);
- X move(STATUS+1, 0);
- X refresh();
- X top_level = false; /* used by tstp() so that right thing is done
- X when process is restarted */
- X if(! vfork()) {
- X (void)sprintf(str, "+%s", curflr->name);
- X argv[0] = SORTM; argv[1] = str;
- X for(i=2, tmp=s1 ; *tmp != '\0' ; i++) {
- X argv[i] = tmp;
- X tmp = next_token(tmp);
- X }
- X argv[i] = 0;
- X no_control();
- X execvp(SORTM, argv);
- X (void)printf("Warning: can't execute %s\n", SORTM);
- X exit(0);
- X }
- X oldint = signal(SIGINT, SIG_IGN);
- X oldquit = signal(SIGQUIT, SIG_IGN);
- X (void)wait(&status);
- X (void)signal(SIGINT, oldint);
- X (void)signal(SIGQUIT, oldquit);
- X top_level = true;
- X to_control();
- X hold_end(); /* wait for user to want to continue - may wish
- X to read error messages */
- X clear();
- X move(STATUS, 0);
- X refresh_folder();
- X}
- END_OF_call.c
- if test 10995 -ne `wc -c <call.c`; then
- echo shar: \"call.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f init.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"init.c\"
- else
- echo shar: Extracting \"init.c\" \(11104 characters\)
- sed "s/^X//" >init.c <<'END_OF_init.c'
- X#ifndef lint
- Xstatic char *RCS_init_c = "$Id: init.c,v 1.3 90/04/23 14:41:11 rogers Exp $";
- X#endif
- X
- X/* --------------------
- X vmail -- init.c
- X
- X Initialisation routines - setting ttystate, finding valid folders,
- X trapping signals.
- X
- X Ttystate is controlled by a mix of curses and ioctl. For simplicity,
- X initial setups are done with curses. Curses is also used for basic
- X screen manipulation. However, for speed ioctl is used in switching
- X in and out of normal terminal state.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X#include <signal.h>
- X
- Xstatic struct sgttyb tty, t_tty; /* for holding tty state */
- Xstatic struct tchars chrs, t_chrs;
- Xstatic struct ltchars lchrs, t_lchrs;
- X
- Xstatic char termcap[1024], /* termcap entry */
- X *cur_folder; /* initial current folder */
- X
- Xsig_type tstp(), tint();
- X
- X/* --------------------
- X Start-up routine - set terminal control, signals, etc.
- X-------------------- */
- Xvoid
- Xinit(argc, argv)
- X int argc;
- X char **argv;
- X{
- X folder ftmp, find_mail();
- X char *pargv[20], /* argv from profile */
- X *profile = (char *) NULL, /* location of MH profile */
- X *home = (char *) NULL, /* home directory */
- X *term = (char *) NULL; /* terminal type */
- X int pargc = 0; /* argc from profile */
- X
- X get_home(&home);
- X get_env(&term, &profile, home);
- X (void)tgetent(termcap, term);
- X cols = tgetnum("co");
- X /* lines holds no. of lines for headers, ie "li" less STATUS, TITLE */
- X lines = tgetnum("li") - 2;
- X (void)ioctl(0, TIOCGETP, (caddr_t)&tty);
- X (void)ioctl(0, TIOCGETP, (caddr_t)&chrs);
- X (void)ioctl(0, TIOCGETP, (caddr_t)&lchrs);
- X
- X read_profile(&pargc, pargv, profile, home);
- X process_args(pargc, pargv);
- X find_folders();
- X mark_valid_folders(pargc, pargv);
- X /* give precedence to command line args => process second */
- X mark_valid_folders(argc, argv);
- X for(ftmp=folders ; ftmp != (folder) NULL ;)
- X if(ftmp->valid)
- X ftmp = find_mail(ftmp, true);
- X else
- X ftmp = ftmp->next;
- X if(curflr->valid == EMPTY) {
- X (void)printf("%s: folder empty.\n", curflr->name);
- X exit(1);
- X }
- X /* find last instance of initial folder */
- X LAST_OF_NAME(curflr);
- X curmail = curflr->mail;
- X
- X (void)initscr();
- X (void)crmode();
- X (void)noecho();
- X (void)nonl();
- X
- X (void)signal(SIGTSTP, tstp);
- X (void)signal(SIGINT, tint);
- X
- X (void)ioctl(0, TIOCGETP, (caddr_t)&t_tty);
- X (void)ioctl(0, TIOCGETP, (caddr_t)&t_chrs);
- X (void)ioctl(0, TIOCGETP, (caddr_t)&t_lchrs);
- X
- X y = FIRST;
- X display_page();
- X}
- X
- X
- X/* --------------------
- X Find user name, home directory.
- X-------------------- */
- Xvoid
- Xget_home(home)
- X char **home;
- X{
- X struct passwd *pwent, *getpwuid();
- X#ifdef vax
- X uid_t getuid();
- X#endif
- X
- X pwent = getpwuid((int)getuid());
- X *home = NEWSTR(strlen(pwent->pw_dir)+1);
- X (void)strcpy(*home, pwent->pw_dir);
- X if(access(*home, R_OK | W_OK | X_OK)) {
- X (void)printf("%s: no permissions.\n", *home);
- X exit(1);
- X }
- X user = NEWSTR(strlen(pwent->pw_name)+1);
- X (void)strcpy(user, pwent->pw_name);
- X}
- X
- X
- X/* --------------------
- X Find pager, editor, shell, terminal type, MH profile - defaults are PAGER,
- X EDITOR, SHELL, none, PROFILE. Set by PAGER, EDITOR, SHELL, TERM, MH
- X environment variables.
- X-------------------- */
- Xvoid
- Xget_env(term, profile, home)
- X char **term, **profile, *home;
- X{
- X char **tmp;
- X
- X for(tmp = environ ; *tmp != (char *) NULL ; tmp++)
- X if(!strncmp("PAGER=", *tmp, 6)) {
- X pager = NEWSTR(strlen(*tmp)-4);
- X (void)strcpy(pager, *tmp+6);
- X } else if(!strncmp("EDITOR=", *tmp, 7)) {
- X editor = NEWSTR(strlen(*tmp)-5);
- X (void)strcpy(editor, *tmp+7);
- X } else if(!strncmp("SHELL=", *tmp, 6)) {
- X shell = NEWSTR(strlen(*tmp)-4);
- X (void)strcpy(shell, *tmp+6);
- X } else if(!strncmp("TERM=", *tmp, 5)) {
- X *term = NEWSTR(strlen(*tmp)-3);
- X (void)strcpy(*term, *tmp+5);
- X } else if(!strncmp("MH=", *tmp, 3)) {
- X *profile = NEWSTR(strlen(*tmp)-1);
- X (void)strcpy(*profile, *tmp+3);
- X }
- X if(*term == (char *) NULL) {
- X (void)printf("Terminal type unknown\n");
- X exit(1);
- X }
- X if(*profile == (char *) NULL) {
- X *profile = NEWSTR(strlen(home)+strlen(PROFILE)+2);
- X (void)sprintf(*profile, "%s/%s", home, PROFILE);
- X }
- X if(pager == (char *) NULL) {
- X pager = NEWSTR(strlen(PAGER)+1);
- X (void)strcpy(pager, PAGER);
- X }
- X if(shell == (char *) NULL) {
- X shell = NEWSTR(strlen(SHELL)+1);
- X (void)strcpy(shell, SHELL);
- X }
- X if(editor == (char *) NULL) {
- X editor = NEWSTR(strlen(EDITOR)+1);
- X (void)strcpy(editor, EDITOR);
- X }
- X}
- X
- X
- Xstatic char argkeep[LEN]; /* storage for args from profile */
- X
- X/* --------------------
- X Find mail directory, current-folder, context, default options.
- X-------------------- */
- Xvoid
- Xread_profile(pargc, pargv, profile, home)
- X int *pargc;
- X char **pargv, *profile, *home;
- X{
- X FILE *fp, *fopen();
- X char str[LEN], *ptr, iscontext[LEN], *index(), *next_token();
- X
- X if((fp = fopen(profile, "r")) == (FILE *) NULL) {
- X (void)printf("Profile: %s: cannot open.\n", profile);
- X exit(1);
- X }
- X *iscontext = '\0';
- X while(fgets(str, LEN, fp) != (char *) NULL) {
- X /* get entries from profile */
- X if(lstrncmp("context:", str, 8) == 0 && *(ptr=str+8) != '\0') {
- X squash(str);
- X (void)strcpy(iscontext, str+8);
- X } else if(lstrncmp("vmail:", str, 6) == 0 && *(ptr=str+6) != '\0') {
- X for( ; *ptr == ' ' || *ptr == '\t' ; ptr++)
- X ;
- X *index(ptr, '\n') = '\0';
- X (void)strcpy(argkeep, ptr);
- X for(ptr=argkeep ; *ptr != '\0' ; ) {
- X pargv[(*pargc)++] = ptr;
- X ptr = next_token(ptr);
- X }
- X } else if(lstrncmp("path:", str, 5) == 0 && *(ptr=str+5) != '\0') {
- X squash(str);
- X if(*ptr == '/') { /* full pathname */
- X mail_dir = NEWSTR(strlen(ptr)+1);
- X (void)strcpy(mail_dir, ptr);
- X } else {
- X mail_dir = NEWSTR(strlen(home)+strlen(ptr)+1);
- X (void)sprintf(mail_dir, "%s/%s", home, ptr);
- X }
- X } else if(lstrncmp("folder-protect:", str, 15) == 0 &&
- X *(str+15) != '\0') {
- X squash(str);
- X folder_protect = atoo(str+15);
- X } else if(lstrncmp("current-folder:", str, 15) == 0 &&
- X *(str+15) != '\0') {
- X squash(str);
- X cur_folder = NEWSTR(strlen(str+15)+1);
- X (void)strcpy(cur_folder, str);
- X }
- X }
- X (void)fclose(fp);
- X if(mail_dir == (char *) NULL) {
- X mail_dir = NEWSTR(strlen(home)+strlen(MAILDIR)+2);
- X (void)sprintf(mail_dir, "%s/%s", home, str+6);
- X }
- X if(access(mail_dir, R_OK | W_OK | X_OK)) {
- X (void)printf("%s: no permissions.\n", mail_dir);
- X exit(1);
- X }
- X if(*iscontext == '\0')
- X (void)strcpy(iscontext, CONTEXT);
- X context = NEWSTR(strlen(mail_dir)+strlen(iscontext)+2);
- X (void)sprintf(context, "%s/%s", mail_dir, iscontext);
- X if(access(context, R_OK | W_OK)) {
- X (void)printf("%s: no permissions.\n", context);
- X exit(1);
- X }
- X if(cur_folder == (char *) NULL)
- X cur_folder = CURFOL;
- X}
- X
- X
- X/* --------------------
- X Squash spaces, tabs, newlines out of given string.
- X-------------------- */
- Xvoid
- Xsquash(str)
- X char *str;
- X{
- X int i, j;
- X
- X for(i=0, j=0 ; (str[j] = str[i]) != '\0' ; i++)
- X if(str[j] != ' ' && str[j] != '\t' && str[j] != '\n')
- X j++;
- X}
- X
- X
- X/* --------------------
- X Mark folders as specified by setenv, command line. At startup, default
- X is for only active folder to be cur_folder.
- X-------------------- */
- Xvoid
- Xmark_valid_folders(argc, argv)
- X int argc;
- X char **argv;
- X{
- X char *name;
- X folder f;
- X
- X name = cur_folder;
- X /* find valid folders - mark all folders from argv as valid */
- X for(; argc > 0 ; argc--, argv++)
- X if(**argv == '+') /* startup folder */
- X name = (*argv) + 1;
- X else if(**argv != '-') { /* not a flag */
- X GOTO_NAME(f, *argv);
- X if(f == (folder) NULL)
- X (void)printf("Warning: no such folder as %s\n", *argv);
- X else
- X f->valid = true;
- X }
- X GOTO_NAME(f, name);
- X if(f == (folder) NULL) {
- X (void)printf("%s does not exist\n", name);
- X exit(1);
- X }
- X f->valid = true;
- X curflr = f;
- X}
- X
- X
- X/* --------------------
- X Reset terminal, clean up.
- X-------------------- */
- Xvoid
- Xto_normal()
- X{
- X move(lines+FIRST-1, 0);
- X refresh();
- X no_control();
- X (void)printf("\n");
- X}
- X
- X
- X/* --------------------
- X Reset terminal.
- X-------------------- */
- Xvoid
- Xno_control()
- X{
- X int x, y;
- X char c;
- X
- X#ifdef STANDOUT_CLEANUP
- X /*
- X * The following code forces curses to issue a standend if it has
- X * one pending.
- X */
- X
- X getyx(stdscr, y, x);
- X c = inch() & 0x7f;
- X if (c == 'a') {
- X addch('b');
- X }
- X else {
- X addch('a');
- X }
- X move(y, x);
- X refresh();
- X move(y, x);
- X addch(c);
- X move(y, x);
- X refresh();
- X#endif
- X
- X (void)ioctl(0, TIOCSETP, (caddr_t)&tty);
- X (void)ioctl(0, TIOCSETP, (caddr_t)&chrs);
- X (void)ioctl(0, TIOCSETP, (caddr_t)&lchrs);
- X}
- X
- X
- X/* --------------------
- X Set terminal.
- X-------------------- */
- Xvoid
- Xto_control()
- X{
- X (void)ioctl(0, TIOCSETP, (caddr_t)&t_tty);
- X (void)ioctl(0, TIOCSETP, (caddr_t)&t_chrs);
- X (void)ioctl(0, TIOCSETP, (caddr_t)&t_lchrs);
- X}
- X
- X
- X#define mask(s) (1 << ((s)-1))
- X
- X/* --------------------
- X Trap for ^Z.
- X-------------------- */
- Xsig_type
- Xtstp()
- X{
- X int x, y;
- X
- X getyx(curscr, y, x);
- X to_normal();
- X fix_mh();
- X
- X (void)signal(SIGTSTP, SIG_DFL);
- X (void)sigsetmask(sigblock(0) &~ mask(SIGTSTP));
- X (void)kill(0, SIGTSTP);
- X (void)sigblock(mask(SIGTSTP));
- X (void)signal(SIGTSTP, tstp);
- X
- X if(top_level) {
- X to_control();
- X touchwin(curscr);
- X (void)wmove(curscr, y, x);
- X (void)wrefresh(curscr);
- X }
- X}
- X
- X
- X/* --------------------
- X Trap for ^?.
- X-------------------- */
- X
- Xsig_type
- Xtint()
- X{
- X touchwin(stdscr);
- X addstatus("-- interrupt --", true);
- X longjmp(env, 0); /* jump to main */
- X}
- X
- X
- X/* --------------------
- X Convert an ascii string to octal.
- X-------------------- */
- Xint
- Xatoo(str)
- X char *str;
- X{
- X int i;
- X
- X for(; *str < '0' && *str > '7' ; str++)
- X ;
- X for(i=0 ; *str >= '0' && *str <= '7' ; str++)
- X i = i*8 + *str - '0';
- X return(i);
- X}
- X
- X
- X/* --------------------
- X Update MH environment - context and current mail item of current folder.
- X-------------------- */
- Xfix_mh()
- X{
- X char str[LEN], buf[20];
- X
- X update(context, "Current-Folder:", curflr->name, 15);
- X (void)sprintf(str, "%s/%s/%s", mail_dir, curflr->name, SEQU);
- X (void)sprintf(buf, "%d", curmail->number);
- X update(str, "cur:", buf, 4);
- X}
- X
- X
- X/* --------------------
- X Update file, replacing line beginning with match of len by "match new".
- X-------------------- */
- Xupdate(file, match, new, len)
- X char *file, *match, *new;
- X int len;
- X{
- X FILE *fp, *tmp, *fopen();
- X bool change = false;
- X char *mktemp(), *fgets();
- X char str[LEN], *name = mktemp("/tmp/vmail.XXXXXX");
- X
- X if((fp = fopen(file, "r")) == (FILE *) NULL) {
- X if((fp = fopen(file, "w+")) == (FILE *) NULL)
- X (void)printf("Can't open %s for writing\n", file);
- X else {
- X (void)fprintf(fp, "%s %s\n", match, new);
- X (void)fclose(fp);
- X }
- X } else {
- X if((tmp = fopen(name, "w+")) == (FILE *) NULL)
- X (void)printf("Can't open %s\n", file);
- X else {
- X while(fgets(str, LEN, fp) != (char *) NULL)
- X if(lstrncmp(str, match, len) == 0) {
- X change = true;
- X (void)fprintf(tmp, "%s %s\n", match, new);
- X } else
- X (void)fprintf(tmp, "%s", str);
- X if(! change)
- X (void)fprintf(tmp, "%s %s\n", match, new);
- X (void)fclose(fp);
- X (void)fclose(tmp);
- X if((fp = fopen(file, "w+")) == (FILE *) NULL)
- X (void)printf("Can't open %s for writing\n", file);
- X else {
- X tmp = fopen(name, "r");
- X while(fgets(str, LEN, tmp) != (char *) NULL)
- X (void)fprintf(fp, "%s", str);
- X (void)fclose(fp);
- X (void)fclose(tmp);
- X (void)unlink(name);
- X }
- X }
- X }
- X}
- END_OF_init.c
- if test 11104 -ne `wc -c <init.c`; then
- echo shar: \"init.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main.c\"
- else
- echo shar: Extracting \"main.c\" \(9902 characters\)
- sed "s/^X//" >main.c <<'END_OF_main.c'
- X#ifndef lint
- Xstatic char *RCS_main_c = "$Id: main.c,v 1.4 91/03/08 15:57:32 jamesp Exp $";
- X#endif
- X
- X/* --------------------
- X vmail -- main.c
- X
- X Definitions of global variables, main switch.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X
- Xfolder folders = (folder) NULL, curflr, alternate = (folder) NULL;
- Xitem curmail;
- Xchar *user, *pager = (char *) NULL, *editor = (char *) NULL,
- X *mail_dir = (char *) NULL, *shell = (char *) NULL, *context;
- Xbool top_level = true, do_flush = true, comp_args = true, repl_args = true,
- X forw_args = true, sort_args = true, burst_args = true,
- X dist_args = true;
- Xint lines, cols, y, folder_protect = FPROT;
- Xjmp_buf env;
- X
- X#define HELP (sizeof(help_scr) / sizeof(*help_scr))
- X
- Xchar *help_scr[] = {
- X" . Re-execute last command (if one of acdDefirR)",
- X" (on repeat, r does not prompt for folder)",
- X" /<exp> Search forwards for title with <exp> (/ to repeat)",
- X" ?<exp> Search backwards for title with <exp> (? to repeat)",
- X" <space> Show current mail item",
- X" [n]<return> Go forward one (or n) active page(s) of mail items",
- X" [n]<backspace> Go back one (or n) active page(s) of mail items",
- X" ^L Refresh",
- X" ^R Refresh item listing, to match current mh folder",
- X" ! Invoke shell",
- X" | Pipe current mail item into command",
- X" ^ Go to first active page",
- X" $ Go to last active page",
- X" a Answer current mail item (call to \"repl\")",
- X" b Burst current mail item as a digest",
- X" c Compose new mail item (call to \"comp\")",
- X" C Go to folder chooser",
- X" [n]d Delete current (or next inclusive n) mail item(s)",
- X" D Delete current mail item, show next",
- X" e Edit current mail item",
- X" f Forward current mail item (call to \"forw\")",
- X" F List all folders",
- X" g,G Go to named (or alternate) folder",
- X" h Show this page",
- X" [n]H Go to top of page (or nth from top line)",
- X" i Incorporate new mail (call to \"inc\")",
- X" [n]j Move cursor down one (or n) line(s)",
- X" [n]k Move cursor up one (or n) line(s)",
- X" [n]L Go to bottom of page (or nth from bottom line)",
- X" M Go to middle of page",
- X" [n]n Go forward one (or n) folders, make new folder active",
- X" [n]p Go back one (or n) folders, make new folder active",
- X" P Print name of alternate folder",
- X" q Exit from vmail",
- X" r,R Refile item in named (or previous) folder",
- X" s Save current item in named file",
- X" S Sort mail items by date",
- X" t Distribute mail item to new recipients (calls 'dist')",
- X" u Undo most recent deletion (1 mail item only)",
- X" v Make current folder inactive",
- X" z Pack current folder"
- X};
- X
- X
- X#define USAGE (void)printf( \
- X"Usage: vmail [-inc] [-flush] [-comp] [-forw] [-ans] [+curfolder] folders ...\n"), \
- X exit(1)
- X
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X char c, last = '\0', get_number(), flushin();
- X int count = 1, /* accumulate count to give to command */
- X pcount = 1;
- X bool flag = false; /* used to check whether to reset count */
- X
- X argc--, argv++;
- X
- X process_args(argc, argv);
- X#ifndef VERSION
- X#define VERSION "(local version)"
- X#endif
- X (void)printf("vmail %s -- reading mail headers\n", VERSION);
- X init(argc, argv);
- X (void)setjmp(env); /* return point from interrupt */
- X c = flushin();
- X for(;;) {
- X while(c == '.')
- X if(last == '\0') {
- X beep();
- X c = flushin();
- X } else {
- X count = pcount;
- X c = last;
- X }
- X switch(c) {
- X case '|': /* pipe mail to command */
- X do_pipe();
- X break;
- X case '!': /* call shell */
- X call_shell();
- X break;
- X case '/': /* search forwards */
- X search(true);
- X break;
- X case '?': /* search backwards */
- X search(false);
- X break;
- X case '^': /* first active page */
- X goto_first_page();
- X break;
- X case '$': /* last active page */
- X goto_last_page();
- X break;
- X case '\n': /* next folder */
- X case '\r': /* next folder */
- X next_page(count, true);
- X break;
- X case ' ': /* show current item */
- X show_mail();
- X break;
- X case DEL: /* previous folder */
- X case '\b': /* previous folder */
- X prev_page(count, true);
- X break;
- X case 'a': /* answer - call to repl */
- X repl();
- X break;
- X case 'b': /* burst current mail item */
- X burst_item();
- X break;
- X case 'c': /* compose - fork of comp */
- X comp();
- X break;
- X case 'C': /* go to folder chooser */
- X choose();
- X break;
- X case 'd': /* delete item */
- X delete_item(count);
- X break;
- X case 'D': /* delete item, show next */
- X (void)change_item(false);
- X show_mail();
- X break;
- X case 'e': /* edit current mail item */
- X edit();
- X break;
- X case 'f': /* forward - call to forw */
- X forw();
- X break;
- X case 'F': /* list all folders */
- X list_folders();
- X break;
- X case 'g': /* go to named folder */
- X goto_folder(true);
- X break;
- X case 'G': /* go to last-named folder */
- X goto_folder(false);
- X break;
- X case 'h': /* help */
- X help();
- X break;
- X case 'H': /* go to top of page */
- X cursor_first(count);
- X break;
- X case 'i': /* inc */
- X inc();
- X break;
- X case 'j': /* cursor down */
- X cursor_down(count);
- X break;
- X case 'k': /* cursor up */
- X cursor_up(count);
- X break;
- X case CTRL_L: /* redraw */
- X display_page();
- X break;
- X case 'L': /* go to bottom of page */
- X cursor_last(count);
- X break;
- X case 'M': /* go to middle of page */
- X cursor_middle();
- X break;
- X case 'n': /* next folder - load if not there */
- X goto_next_folder(count);
- X break;
- X case 'p': /* prev folder - load if not there */
- X goto_prev_folder(count);
- X break;
- X case 'P': /* print name of last-named folder */
- X show_folder();
- X break;
- X case 'q': /* quit */
- X to_normal();
- X fix_mh();
- X exit(0);
- X break;
- X case 'r': /* move item to named folder */
- X move_item(true);
- X break;
- X case CTRL_R: /* reread current folder */
- X refresh_folder();
- X break;
- X case 'R': /* move item to previous folder */
- X move_item(false);
- X break;
- X case 's': /* save item in named file */
- X save_item();
- X break;
- X case 'S': /* sort current folder */
- X sort_folder();
- X break;
- X case 't': /* dist a mail item to new people */
- X dist_item();
- X break;
- X case 'u': /* undo */
- X undo();
- X break;
- X case 'v': /* make folder inactive */
- X inactive();
- X break;
- X case 'z': /* pack current folder */
- X pack_folder();
- X break;
- X case '0': /* start of count */
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X c = get_number(c, &count);
- X flag = true;
- X break;
- X default:
- X addstatus("command unknown -- `h' for help", true);
- X break;
- X }
- X switch(c) {
- X /* repeatable commands */
- X case 'r': /* refile item in named folder */
- X last = 'R';
- X pcount = 1;
- X break;
- X case 'a': /* reply - call to repl */
- X case 'c': /* compose - fork of comp */
- X case 'd': /* delete item */
- X case 'D': /* delete item, show next */
- X case 'e': /* edit current mail item */
- X case 'f': /* forward - call to forw */
- X case 'i': /* inc */
- X case 'R': /* refile to previous folder */
- X case 't': /* redistribute - call to dist */
- X case 'w': /* write to file */
- X last = c;
- X pcount = count;
- X break;
- X default:
- X break;
- X }
- X if(!flag) {
- X c = flushin();
- X count = 1;
- X } else {
- X flag = false;
- X }
- X }
- X}
- X
- X
- X/* --------------------
- X Read a number from terminal.
- X-------------------- */
- Xchar
- Xget_number(c, count)
- X char c;
- X int *count;
- X{
- X *count = c - '0';
- X while((c = getchar()) >= '0' && c <= '9')
- X *count = *count * 10 + c - '0';
- X return(c);
- X}
- X
- X
- XWINDOW *helpwin = (WINDOW *) NULL;
- X
- X/* --------------------
- X Display help messages on help screen.
- X-------------------- */
- Xhelp()
- X{
- X WINDOW *newwin();
- X int i, j;
- X
- X if(helpwin == (WINDOW *) NULL)
- X helpwin = newwin(0, 0, 0, 0);
- X (void)wclear(helpwin);
- X for(j=i=0 ; i <= HELP ; i++, j++) {
- X if((i+2) % lines == 0) {
- X if(use_prompt(helpwin) == 'q')
- X break;
- X j=0;
- X (void)wclear(helpwin);
- X }
- X if(i >= HELP) {
- X (void)use_prompt(helpwin);
- X break;
- X }
- X mvwaddstr(helpwin, j+1, 0, help_scr[i]);
- X }
- X display_page();
- X}
- X
- X
- X/* --------------------
- X Process arguments, command-line or given in profile.
- X-------------------- */
- Xvoid
- Xprocess_args(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X for( ; argc > 0 ; argc--, argv++)
- X if(!strcmp(argv[0], "-inc")) { /* incorporate mail before starting */
- X if(!vfork()) {
- X execlp(INC, INC, 0);
- X (void)printf("Warning: can't execute %s\n", INC);
- X exit(0);
- X }
- X (void)wait((union wait *)0);
- X (void)printf("\n");
- X } else if(!strcmp(argv[0], "-flush")) /* don't flush typeahead */
- X do_flush = false;
- X else if(!strcmp(argv[0], "-forw")) /* no args to forw */
- X forw_args = false;
- X else if(!strcmp(argv[0], "-comp")) /* no args to comp */
- X comp_args = false;
- X else if(!strcmp(argv[0], "-ans")) /* no args to repl */
- X repl_args = false;
- X else if(!strcmp(argv[0], "-burst")) /* no args to burst */
- X burst_args = false;
- X else if(!strcmp(argv[0], "-dist")) /* no args to dist */
- X dist_args = false;
- X else if(!strcmp(argv[0], "-sort")) /* no args to sort */
- X sort_args = false;
- X else if(*argv[0] == '-') {
- X (void)printf("%s: illegal option\n", argv[0]);
- X USAGE;
- X }
- X}
- END_OF_main.c
- if test 9902 -ne `wc -c <main.c`; then
- echo shar: \"main.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f move.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"move.c\"
- else
- echo shar: Extracting \"move.c\" \(10258 characters\)
- sed "s/^X//" >move.c <<'END_OF_move.c'
- X#ifndef lint
- Xstatic char *RCS_move_c = "$Id: move.c,v 1.3 91/03/08 15:57:57 jamesp Exp $";
- X#endif
- X
- X/* --------------------
- X vmail -- move.c
- X
- X Routines to delete or move a mail item from current folder.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X#include <errno.h>
- X
- Xstatic char prevfile[LEN] = "";
- X
- Xextern int errno;
- X
- X/* --------------------
- X Move current item to folder prevfile (get_name = false) or as read from
- X terminal (get_name = true).
- X-------------------- */
- Xvoid
- Xmove_item(get_name)
- X bool get_name;
- X{
- X char *s, str[LEN], str2[LEN];
- X folder f, new_folder(), create_folder();
- X item m;
- X bool redraw; /* true if screen to be refreshed */
- X int fdi, fdo, i = FIRST-1, num, N;
- X
- X /* get name if required */
- X if(get_name || *prevfile == '\0') {
- X get_string("folder? ", str);
- X if(*str == '\0') {
- X addstatus("no name given for folder", true);
- X return;
- X }
- X (void)strcpy(prevfile, str);
- X } else
- X (void)strcpy(str, prevfile);
- X /* find first page of named folder */
- X (void)sprintf(str2, "refiling to %s ...", str);
- X addstatus(str2, false);
- X GOTO_NAME(f, str);
- X if(f == (folder) NULL) { /* create folder */
- X f = create_folder(str);
- X if(f == (folder) NULL)
- X return;
- X } else {
- X if(f->name == curflr->name) {
- X addstatus("can't move item to current folder", true);
- X return;
- X }
- X if(f->valid) { /* goto last mail item in folder */
- X LAST_OF_NAME(f);
- X for(i=FIRST, m=f->mail ; m->next != (item) NULL ; i++, m=m->next)
- X ;
- X }
- X }
- X /* remember current location of mail */
- X m = curmail;
- X num = curmail->number;
- X s = curflr->name;
- X /* delete item from current folder, update current folder & screen */
- X redraw = change_item(true);
- X if(f->valid) /* update structures of mail items */
- X if(i > lines) {
- X /* create new folder record */
- X f = new_folder(f);
- X f->mail = f->last = m;
- X m->prev = m->next = (item) NULL;
- X N = f->prev->last->number;
- X } else {
- X /* insert at end of list of mail items */
- X m->prev = f->last; m->next = (item) NULL;
- X f->last->next = m;
- X f->last = m;
- X N = m->prev->number;
- X }
- X else
- X N = next_vacant(f);
- X/* to avoid race between "send" or other process in background and vmail
- X foreground, compute next free slot, dont just use given value
- X*/
- X (void)sprintf(str2, "%s/%s/%d", mail_dir, f->name, N);
- X /* loop until unused file name found */
- X for(errno=0 ; (fdo = open(str2, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0
- X && errno == EEXIST ; errno=0) {
- X N = N + 1;
- X (void)sprintf(str2, "%s/%s/%d", mail_dir, f->name, N);
- X }
- X if(f->valid)
- X m->number = N;
- X (void)sprintf(str, "%s/%s/%d", mail_dir, s, num);
- X fdi = open(str, O_RDONLY);
- X while((i = read(fdi, str2, LEN)) > 0) /* copy original to new */
- X (void)write(fdo, str2, i);
- X (void)close(fdi);
- X (void)close(fdo);
- X (void)unlink(str); /* remove original */
- X if(redraw)
- X display_page();
- X else {
- X add_page_header(str);
- X move(y, 0);
- X refresh();
- X }
- X addstatus("refiled", true);
- X if(curflr == (folder) NULL) {
- X to_normal();
- X exit(1);
- X }
- X}
- X
- X
- X/* --------------------
- X Delete count items.
- X-------------------- */
- Xvoid
- Xdelete_item(count)
- X int count;
- X{
- X bool redraw = false;
- X item m;
- X char str[LEN];
- X
- X for( ; count > 0 ; count--) {
- X m = curmail->next;
- X redraw = change_item(false);
- X if(redraw || m != curmail) /* on new page, or last item deleted */
- X break;
- X }
- X if(redraw)
- X display_page();
- X else {
- X add_page_header(str);
- X move(y, 0);
- X refresh();
- X }
- X}
- X
- X
- X/* --------------------
- X Structure for deleted item.
- X-------------------- */
- Xstruct {
- X folder flr;
- X int number;
- X} deleted = {(folder) NULL, 0};
- X
- X
- X/* --------------------
- X Either delete (do_move = false) or prepare to move (do_move = true) item.
- X Delete item from current folder, update screen, find new current folder
- X if current folder has become empty.
- X-------------------- */
- Xbool
- Xchange_item(do_move)
- X bool do_move;
- X{
- X item tmp, m = curmail;
- X folder F, p, f = curflr, pval, nval;
- X char s1[LEN], s2[LEN];
- X bool redraw, doexit = false;
- X
- X if(curmail->next == (item) NULL && curmail->prev == (item) NULL) {
- X /* have last item in page */
- X redraw = true;
- X pval = curflr->prev; PREV_VALID(pval);
- X nval = curflr->next; NEXT_VALID(nval);
- X if(pval == (folder) NULL && nval == (folder) NULL) {
- X /* no more active pages */
- X if(! do_move)
- X addstatus("Deleting last active mail item -- bye", true);
- X doexit = true;
- X } else {
- X /* update pages, pagenum */
- X for(p=curflr->prev ; p != (folder) NULL && p->name == curflr->name
- X ; p=p->prev)
- X p->pages -= 1;
- X for(p=curflr->next ; p != (folder) NULL && p->name == curflr->name
- X ; p=p->next)
- X p->pages -= 1, p->pagenum -= 1;
- X /* find next active page, drop current page from list */
- X if(curflr->prev != (folder) NULL)
- X curflr->prev->next = curflr->next;
- X else
- X folders = curflr->next;
- X if(curflr->next != (folder) NULL)
- X curflr->next->prev = curflr->prev;
- X /*
- X * If the previous page is from the same folder,
- X * move to last item on that page. Otherwise,
- X * move to first page of next folder if it is
- X * available, else move to first page of previous
- X * folder if it is available.
- X */
- X if (pval != (folder) NULL && pval->name == curflr->name) {
- X curflr = pval;
- X curmail = curflr->mail;
- X for ( ; curmail->next != (item) NULL; y++)
- X curmail = curmail->next;
- X }
- X else
- X {
- X curflr = (nval == (folder) NULL) ? pval : nval;
- X curmail = curflr->mail;
- X }
- X }
- X } else {
- X redraw = false;
- X deleteline();
- X /* move first item from next to current */
- X if(curflr->next != (folder) NULL && curflr->name == curflr->next->name)
- X show_title(s1, FIRST+lines-1, curflr->next->mail);
- X for(p=curflr->next ; p != (folder) NULL && p->name == curflr->name ;
- X p=p->next) {
- X tmp = p->mail;
- X p->mail = tmp->next;
- X if(p->mail == (item) NULL) { /* remove folder from list */
- X p->prev->next = p->next;
- X if(p->next != (folder) NULL)
- X p->next->prev = p->prev;
- X /* update page counts */
- X for(F=p->prev ; F != (folder) NULL && F->name == p->name
- X ; F=F->prev)
- X F->pages -= 1;
- X } else
- X p->mail->prev = (item) NULL;
- X p->prev->last->next = tmp;
- X tmp->prev = p->prev->last;
- X tmp->next = (item) NULL;
- X p->prev->last = tmp;
- X }
- X /* delete item from linked list of items */
- X if(m->prev == (item) NULL)
- X curflr->mail = m->next;
- X else
- X m->prev->next = m->next;
- X if(m->next == (item) NULL) {
- X curflr->last = m->prev;
- X curmail = m->prev;
- X y--;
- X } else {
- X m->next->prev = m->prev;
- X curmail = m->next;
- X }
- X move(y, 0);
- X }
- X if(! do_move) {
- X deleted.flr = f;
- X deleted.number = m->number;
- X (void)sprintf(s1, "%s/%s/%d", mail_dir, f->name, m->number);
- X (void)sprintf(s2, "%s/%s/#%d", mail_dir, f->name, m->number);
- X (void)rename(s1, s2);
- X if(doexit) {
- X to_normal();
- X exit(0);
- X }
- X }
- X return(redraw);
- X}
- X
- X
- X/* --------------------
- X Create folder of given name if user agrees, creating directory and
- X entry in linked list of folders.
- X-------------------- */
- Xfolder
- Xcreate_folder(str)
- X char *str;
- X{
- X struct stat statbuf;
- X char str2[LEN], c;
- X folder fnew, p, f;
- X
- X squash(str);
- X (void)sprintf(str2, "%s does not exist (or is empty) - create? ", str);
- X mvaddstr(STATUS, 0, str2); refresh();
- X c = getchar();
- X move(STATUS, 0); clrtoeol(); move(y, 0); refresh();
- X if(c != 'y')
- X return((folder) NULL);
- X for(p=(folder) NULL, f=folders ; f != (folder) NULL &&
- X strcmp(str, f->name) > 0 ; p=f, f=f->next)
- X ;
- X /* create physical folder */
- X (void)sprintf(str2, "%s/%s", mail_dir, str);
- X if(stat(str2, &statbuf)) { /* doesn't exist */
- X if(mkdir(str2, folder_protect)) {
- X addstatus("Cannot make folder", true);
- X return((folder) NULL);
- X }
- X } else
- X if(!(statbuf.st_mode & S_IREAD) || !(statbuf.st_mode & S_IWRITE)
- X || !(statbuf.st_mode & S_IEXEC)) {
- X addstatus("Cannot write in folder", true);
- X return((folder) NULL);
- X }
- X /* make a new folder record, insert it */
- X fnew = NEW(mail_folder);
- X fnew->name = NEWSTR(strlen(str)+1);
- X (void)strcpy(fnew->name, str);
- X fnew->mail = fnew->last = (item) NULL;
- X fnew->next = fnew->prev = (folder) NULL;
- X fnew->pages = fnew->pagenum = 1;
- X fnew->valid = false;
- X if(p == (folder) NULL) {
- X fnew->next = folders;
- X folders->prev = fnew;
- X folders = fnew;
- X } else {
- X p->next = fnew;
- X if(f != (folder) NULL)
- X f->prev = fnew;
- X fnew->prev = p;
- X fnew->next = f;
- X }
- X return(fnew);
- X}
- X
- X
- X/* --------------------
- X Crude undo. Sophisticated undo rather too painful to code.
- X-------------------- */
- Xvoid
- Xundo()
- X{
- X folder f = deleted.flr, p;
- X char s1[LEN], s2[LEN];
- X
- X if(f == (folder) NULL) {
- X addstatus("nothing to undo", true);
- X return;
- X } else {
- X addstatus("undoing ...", true);
- X deleted.flr = (folder) NULL;
- X }
- X (void)sprintf(s1, "%s/%s/#%d", mail_dir, f->name, deleted.number);
- X (void)sprintf(s2, "%s/%s/%d", mail_dir, f->name, deleted.number);
- X (void)rename(s1, s2);
- X /* find first page of folder */
- X p = f; FRST_OF_NAME(p);
- X /* find last page of folder */
- X LAST_OF_NAME(f);
- X curflr = p;
- X p->next = f->next;
- X/* should free old folder/mail records */
- X/* p->valid = false; */
- X p->mail = p->last = (item) NULL;
- X p->pagenum = p->pages = 1;
- X if(p->next != (folder) NULL)
- X p->next->prev = p;
- X (void)find_mail(curflr, false);
- X curmail = curflr->mail;
- X y = FIRST;
- X display_page();
- X}
- X
- X
- X/* --------------------
- X Pack current folder. Unsets "deleted" if last removed record was
- X on current folder.
- X-------------------- */
- Xvoid
- Xpack_folder()
- X{
- X folder f = curflr;
- X item m;
- X char path[LEN], s1[LEN], s2[LEN];
- X bool found;
- X int newnum = 1;
- X
- X addstatus("Packing folder ...", false);
- X FRST_OF_NAME(f);
- X /* unset undo if packing that folder */
- X if(deleted.flr != (folder) NULL && deleted.flr->name == curflr->name)
- X deleted.flr = (folder) NULL;
- X (void)sprintf(path, "%s/%s/", mail_dir, curflr->name);
- X for( ; f != (folder) NULL && f->name == curflr->name ; f=f->next)
- X for(m=f->mail ; m != (item) NULL ; m=m->next) {
- X for(found=false ; !found && newnum < m->number ; ) {
- X (void)sprintf(s1, "%s%d", path, newnum);
- X if(! access(s1, R_OK))
- X newnum++;
- X else
- X found = true;
- X }
- X if(found) {
- X (void)sprintf(s2, "%s%d", path, m->number);
- X (void)rename(s2, s1);
- X m->number = newnum;
- X }
- X }
- X display_page();
- X}
- END_OF_move.c
- if test 10258 -ne `wc -c <move.c`; then
- echo shar: \"move.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f vmail.1 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"vmail.1\"
- else
- echo shar: Extracting \"vmail.1\" \(10694 characters\)
- sed "s/^X//" >vmail.1 <<'END_OF_vmail.1'
- X.\"
- X.\" $Header: /mnts/metolius/home/jamesp/usr/src/vmail/RCS/vmail.1,v 1.3 91/03/08 15:58:57 jamesp Exp $
- X.\"
- X.TH VMAIL 1 "30 September 1987"
- X.UC Melb
- X.SH NAME
- Xvmail \- tty interface to MH
- X.SH SYNOPSIS
- X\fBvmail\fR
- X[\-ans]
- X[\-burst]
- X[\-comp]
- X[\-dist]
- X[\-flush]
- X[\-forw]
- X[\-inc]
- X[\-sort]
- X[+cur_folder] folders ...
- X.SH DESCRIPTION
- X\fIvmail\fR is a tty interface to the MH mail system.
- XIt combines most of the MH features into a single package, and performs
- Xthe most frequently-used functions considerably faster than the
- XMH equivalents.
- XIn particular, a folder is only scanned once in a \fIvmail\fR
- Xsession; the slow scan-show-rmm-scan cycle of MH is eliminated.
- XAlso, \fIvmail\fR tends to be simpler for new users to learn than
- Xthe MH system.
- X.SH "STARTING UP"
- X.LP
- XWhen \fIvmail\fR is invoked, it loads mail headers for the folders
- Xwhich will initially be active.
- XThe default is for \fBinbox\fR (or the MH profile field Current-Folder)
- Xto be the only active folder.
- X(Other folders may be made active during the course of a session.)
- XThere are a number of command-line flags.
- X\fB\-inc\fR asks \fIvmail\fR to incorporate mail before loading any folders.
- X\fB\-flush\fR instructs \fIvmail\fR not to flush typeahead.
- X\fB\-comp\fR, \fB\-forw\fR, \fB\-ans\fR,
- X\fB\-dist\fR, \fB\-burst\fR, and \fB\-sort\fR specify that \fIcomp\fR, \fIforw\fR,
- X\fIrepl\fR (`answer'), \fIdist\fR, \fIburst\fR, and \fIsortm\fR
- Xrespectively do not require that the user give
- Xarguments; see the commands \fBc\fR, \fBf\fR, \fBa\fR,
- X\fBt\fR, \fBb\fR, and \fBS\fR.
- XArguments may also be set by the profile component \fBvmail\fR.
- XTypical usage of \fIvmail\fR might be:
- X.sp
- X vmail +priv inbox outbox
- X.sp
- Xto start up \fIvmail\fR with folders \fBpriv\fR, \fBinbox\fR, and
- X\fBoutbox\fR active and with \fBpriv\fR as the current folder.
- X\fIvmail\fR might then print
- X.nf
- X.sp
- X\f(as Vmail 9/87 -- reading mail headers
- X inbox: 122-279 (32 items)
- X outbox: 1-95 (19 items)
- X priv: 2-19 (5 items)\fR
- X.sp
- X.fi
- Xas it loaded the named folders.
- XWhen loading completed it would bring up the screen
- Xrepresenting the mail items in the folder \fBpriv\fR.
- X.nf
- X.sp
- X\f(as priv (page 1 of 1)
- X
- X 2 17-06-86 fred@munnari Just testing << Are you receiving
- X 6 7-11-86 To: fred, nerk A promise << The commitment: Dinn
- X 7 9-05-87 bill thanks for everything, but << wha
- X 12 11-05-87 \-bill Re: thanks for everything, but <<
- X 19 9-05-87 To: bill Re: thanks for everything, but <<\fR
- X.sp
- X.fi
- X(Note that the dates in the example are in British format; a US installation
- Xwould have the US form.)
- XThe `\fB\-\fR' indicates that a reply has been sent to that piece of mail.
- XText to the left of `\fB<<\fR' is the subject, other text is the
- Xfirst part of the body.
- XThe user could now move up and down between mail items with \fBk\fR and
- X\fBj\fR, show the current mail item with \fB<space>\fR, delete the current
- Xmail item with \fBd\fR, or forward or answer it with \fBf\fR or \fBa\fR.
- X.LP
- XIf the folder \fBpriv\fR contained more mail items than could be
- Xdisplayed on a screen, \fBpriv\fR would be broken into a number of pages.
- X\fIvmail\fR has one or more pages for each active folder.
- XThe user can move between pages, which are ordered alphabetically on
- Xfolder name, by typing \fB<return>\fR and \fB<backspace>\fR
- X(forwards and backwards respectively).
- X.SH "THE DETAILS"
- X.LP
- XFor those who like to mix use of MH and \fIvmail\fR, \fIvmail\fR
- Xupdates the MH environment on \fBq\fR (quit), \fB!\fR (call shell)
- Xand \fB^Z\fR (suspend).
- XSpecifically, the fields `Current-Folder' in \fBcontext\fR and
- X`cur' in \fBmh-profile\fR are updated to be the current folder and
- Xcurrent mail item respectively.
- XAlso, the \fB^R\fR command is useful for getting
- Xvmail to sync up and recognize changes made by mh commands not
- Xunder its control.
- X.LP
- XThe following points are relevant to all \fIvmail\fR commands.
- XFirst, type-ahead is flushed (as in \fIrn\fR), so any commands
- Xtyped ahead of time will be ignored.
- XSecond, \fIvmail\fR always remembers the name of an ``alternate
- Xfolder'', the last folder other than the current folder with which
- Xthere has been an interaction (such as the folder to which an item
- Xwas refiled, or the previous current folder).
- XThis alternate folder is used by a number of commands.
- XThird, some commands may be preceded by a count.
- X.LP
- XThe following is a complete list of \fIvmail\fR commands.
- X.TP 10
- X.B <space>
- XShow current mail item (like \fIshow\fR).
- X.TP 10
- X.B <return>
- XGo to next active page of mail headers (uses count).
- X.TP 10
- X.B <backspace>
- XGo to previous active page of mail headers (uses count).
- X.TP 10
- X.B ^,$
- XGo to the first (or last) active page of mail headers.
- X.TP 10
- X.B /,?
- XSearch forwards (or backwards) through mail headers for the given
- Xregular expression.
- X\fB/<return>\fR will repeat search forwards, \fB?<return>\fR will repeat
- Xthe search backwards.
- XIt is not possible to backspace over \fB/\fR or \fB?\fR; use interrupt
- Xinstead.
- X.TP 10
- X.B .
- XRe-execute last command (if one of acdDefirR).
- X(On repeat, \fBr\fR will not prompt for a folder name.)
- X.TP 10
- X.B ^L
- XRefresh screen.
- X.TP 10
- X.B ^R
- XRefresh list of items for this folder.
- XThis rebuilds the \fIvmail\fR data structures.
- X.B ^R
- Xis useful for resyncing the item listing with changes made by
- X\fIMH\fR commands not performed by vmail itself.
- X.TP 10
- X.B |
- XPipe current mail item into command.
- X.TP 10
- X.B !
- XInvoke your favourite shell (\fIcsh\fR by default).
- X.TP 10
- X.B a
- XAnswer current mail item (call to \fIrepl\fR).
- X\fIvmail\fR will ask for arguments unless \fB\-ans\fR has been set.
- X\fIvmail\fR data structures won't be updated.
- X.TP 10
- X.B b
- XBurst a mail item (call to \fIburst\fR).
- XThis splits a digest or a message carrying several
- Xforwarded messages into individual messages.
- X\fIvmail\fR will ask for arguments unless \fB\-burst\fR has been set.
- X\fIvmail\fR data structures will be updated.
- X.TP 10
- X.B c
- XCompose new mail (call to \fIcomp\fR).
- X\fIvmail\fR will ask for arguments unless \fB\-comp\fR has been set.
- X\fIvmail\fR data structures won't be updated.
- X.TP 10
- X.B C
- XInvoke the folder chooser.
- XThis is a screen which permits users to select a current folder
- Xby moving the cursor to a folder name with \fIvi\fR movement keys
- Xand hitting \fB<space>\fR.
- X.TP 10
- X.B d
- XDelete current mail item (uses count) (like \fIrmm\fR).
- XActually, the mail item is moved from maildir/folder/num to maildir/folder/#num.
- X\fIvi\fR users beware, \fBdd\fR deletes two items of mail.
- X.TP 10
- X.B D
- XDelete current mail item, show next.
- X.TP 10
- X.B e
- XEdit current mail item.
- X.TP 10
- X.B f
- XForward current mail item (call to \fIforw\fR).
- X\fIvmail\fR will ask for arguments unless \fB\-forw\fR has been set.
- X\fIvmail\fR data structures won't be updated.
- X.TP 10
- X.B g,G
- XGo to the named (or go to alternate) folder.
- X.TP 10
- X.B F
- XShow all foldernames.
- X.TP 10
- X.B h
- XDisplay the help screen.
- X.TP 10
- X.B H
- XGo to top of page (or as offset by count).
- X.TP 10
- X.B i
- XIncorporate mail (call to \fIinc\fR).
- X\fIvmail\fR data structures are updated.
- X.TP 10
- X.B j
- XMove cursor down (uses count).
- XAt the bottom of the page, \fBj\fR will go to the top of the next page
- Xof the current folder.
- X.TP 10
- X.B k
- XMove cursor up (uses count).
- XAt the top of the page, \fBk\fR will go to the bottom of the previous page
- Xof the current folder.
- X.TP 10
- X.B L
- XGo to bottom of page (or as offset by count).
- X.TP 10
- X.B M
- XGo to middle of page.
- X.TP 10
- X.B n
- XGo to the next folder, making it active if it is not so already (uses count).
- X.TP 10
- X.B p
- XGo to the previous folder, making it active if it is not so
- Xalready (uses count).
- X.TP 10
- X.B P
- XPrint the name of the alternate folder.
- X.TP 10
- X.B q
- XExit.
- X.TP 10
- X.B r
- XRefile current item into the named folder.
- X.TP 10
- X.B R
- XRefile current item into the last folder to which something was refiled.
- X.TP 10
- X.B s
- XSave current mail item in the named file.
- XMost filename expansions are not recognized, but `~/' and `~user/' are
- Xreplaced by the appropriate paths.
- X.TP 10
- X.B S
- XSort the current folder (call to \fIsortm\fR).
- XThis sorts all the messages in the current folder
- Xin order of the Date: lines.
- X\fIvmail\fR will ask for arguments unless \fB\-sort\fR has been set.
- X\fIvmail\fR data structures will be updated.
- X.TP 10
- X.B t
- XDistribute an existing mail item to new recipients
- X(call to \fIdist\fR).
- X\fIvmail\fR will ask for arguments unless \fB\-dist\fR has been set.
- X\fIvmail\fR data structures won't be updated.
- X.TP 10
- X.B u
- XUndo most recent deletion.
- X.TP 10
- X.B v
- XMake the current folder inactive.
- X.TP 10
- X.B z
- XPack the current folder.
- X.LP
- XThe commands \fBa\fR, \fBc\fR, \fBt\fR and \fBf\fR update the physical folders,
- Xbut the corresponding pages of mail headers in \fIvmail\fR are not updated.
- X\fB^R\fR can be used to force the \fIvmail\fR
- Xrepresentation of a folder to come up to date.
- X.LP
- X\fIvmail\fR recognizes the following environment variables.
- XWhere they describe an executable, a full path name should be given.
- X.TP 10
- X.B SHELL
- XSubshell invoked on `!'.
- XDefault is \fI/bin/csh\fR.
- X.TP 10
- X.B PAGER
- XDefault is \fI/usr/ucb/more\fR.
- X.TP 10
- X.B EDITOR
- XUsed for editing stored mail.
- XThe default is \fI/usr/ucb/vi\fR.
- X.TP 10
- X.B MH
- XUsed to identify the MH profile.
- XFrom the profile, \fIvmail\fR recognizes \fBPath\fR, \fBMsg-protect\fR
- Xand \fBFolder-protect\fR.
- XThe calls to MH utilities use the MH profile as appropriate.
- XThe default is \fB~/.mh_profile\fR.
- X.SH "PROFILE ENTRIES"
- X.LP
- XFolder-Protect (protection for new folders)
- X.LP
- XPath (of mail directory)
- X.LP
- XCurrent-Folder (for startup folder)
- X.LP
- XVmail (list of arguments)
- X.SH FILES
- X.LP
- X$HOME/.mh_profile
- X.LP
- X$HOME/Mail
- X.LP
- X$HOME/Mail/context
- X.SH "SEE ALSO"
- Xburst(1),
- Xcomp(1),
- Xdist(1),
- Xforw(1),
- Xinc(1),
- Xrepl(1),
- Xsortm(1).
- X.SH HISTORY
- X.LP
- XOriginal program Copyright 1987 J. Zobel, jz@mulga.oz.au.
- XPermission for redistribution and modifications were
- Xpermitted,
- Xproviding that the copyright notice remained intact.
- X.LP
- XBug fixes,
- XSparc port,
- Xburst,
- Xdist,
- Xresync commands added by James Perkins 1989-1991,
- Xjamesp@metolius.wr.tek.com.
- X.SH BUGS
- X.LP
- XCheck the alternate folder before using it unless absolutely sure
- Xof its identity; a command may change it unexpectedly.
- X.LP
- XOnly a couple of formats of "Date:" lines are recognized; if the format is
- Xdifferent, the date is replaced by a block of spaces.
- X.LP
- XStartup time is proportional to the number of items in the current folder.
- XIt is therefore better to have a large number of folders each with fewer
- Xmail items than a small number of large folders.
- XMany first-time vmail users find that their inbox is large enough
- X(> 400 items, say) that vmail takes a while to start up \- expect to
- Xspend some time initially decluttering inbox and other large folders.
- X.LP
- XIf your inbox is empty at startup, vmail will
- Ximmediately exit.
- END_OF_vmail.1
- if test 10694 -ne `wc -c <vmail.1`; then
- echo shar: \"vmail.1\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-